﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using VCDIFF.Visit;

namespace VCDIFF.Commands
{
    ///<summary>
    /// RUN: This instruction has two arguments, a size x and a byte b, that will be repeated x times.
    ///</summary>
    public class Run : Command
    {
        public UInt64 Size { get; set; }
        public byte RunByte { get; set; }

        /// <summary>
        /// Run constructor.
        /// </summary>
        /// <param name="size">Repeat factor.</param>
        /// <param name="runByte">Byte that will be repeated.</param>
        public Run(UInt64 size, byte runByte)
        {
            Size = size;
            RunByte = runByte;
        }

        /// <summary>
        /// Execute the run command on the target byte table.
        /// </summary>
        /// <param name="target">Byte table on which we proceed the command.</param>
        /// <returns>Byte table on which the command was done.</returns>
        public override byte[] Execute(byte[] target)
        {
            byte[] runArray = new byte[(UInt64)target.Length + Size];

            int index = 0;

            for (int i = 0; i < target.Length; i++)
            {
                runArray[i] = target[i];
                index++;
            }

            for (int i = index; i < runArray.Length; i++)
                runArray[i] = RunByte;

            return runArray;
        }

        /// <summary>
        /// Returns the encoded byte table of the run command.
        /// </summary>
        /// <returns>The encoded byte table of the run command.</returns>
        public override byte[] ToByteArray()
        {
            byte[] runArray = new byte[3] { 0x02, Convert.ToByte(Size), RunByte };

            return runArray;
        }

        /// <summary>
        /// Writes Run command thanks to a Writer.
        /// </summary>
        /// <param name="writer">Writer who writes Run command.</param>
        public override void Write(Writer writer)
        {
            writer.Visit(this);
        }

        /// <summary>
        /// Accepts a reader and authorizes it to visit this object.
        /// </summary>
        /// <param name="writer">Reader which visits this object.</param>
        public override void Read(Reader reader)
        {
            reader.Visit(this);
        }
    }
}
